<?php
/**
 * Description of Emms_Cron_Payments
 * @author andres
 *
 */
require_once APPLICATION_PATH . '/modules/loan/models/Loans.php';
require_once APPLICATION_PATH . '/modules/loan/models/LoanStatusChanges.php';
require_once APPLICATION_PATH . '/modules/loan/models/LoanWriteOffCharges.php';
require_once APPLICATION_PATH . '/modules/loan/models/LoanWriteOffPayments.php';
require_once APPLICATION_PATH . '/modules/loan/models/Payments.php';
require_once APPLICATION_PATH . '/modules/savings/models/SavingsAccounts.php';

class Emms_Cron_Payments extends Emms_Cron implements Emms_Interface_Cron
{
    private $_pastDueLoans;
    private $_savingsAccounts;
    private $_savingsTransactions;
    private $_payments;
    private $_loans;
    private $_activeLoans;
    private $_loanStatusChanges;
    
    public function __construct() 
    {
        parent::__construct();
        
        $this->_activeLoans = new Zend_Db_Table(array('name' => 'active_loans', 'primary' => 'LoanId'));
        $this->_loans = new Zend_Db_Table(array('name' => 'loans', 'primary' => 'LoanId'));
        $this->_loanStatusChanges = new Zend_Db_Table(array('name' => 'loan_status_changes', 'primary' => 'Id'));
        $this->_payments = new Zend_Db_Table(array('name' => 'payments', 'primary' => 'LoanId'));
        $this->_savingsTransactions = new Zend_Db_Table(array('name' => 'savings_transactions', 'primary' => 'SavingsTransactionId'));
        //$this->_savingsAccounts = new Zend_Db_Table(array('name' => 'view_savings_accounts', 'primary' => 'SavingsAccountId'));
        $this->_savingsAccounts = new SavingsAccounts();
        
        try {
            $viewloans = new Zend_Db_Table(array('name' => 'view_loans', 'primary' => 'LoanId'));
            $this->_pastDueLoans = $viewloans->fetchAll($viewloans->select()
                ->where('Status = "Disbursed"')
                ->where('CurrentDate >= NextPaymentDate')//->limit(10)->where('ClientId = 42313')
                ->order('LoanId'));
        } catch  (Zend_Exception $e) {
            throw $e;
        }
    }
    
    public function update()
    {
        $i = 0;
        $j = 0;
        foreach($this->_pastDueLoans as $row) {
            $this->db->beginTransaction();
            try {
                $i++;
                $plan = new Emms_PmtPlan(new Emms_Loan($row->LoanId));
                $activeLoanUpdate = false;
                foreach($plan->getSchPmtObj() as $schPayment) {
                    if($schPayment->Paid) continue;
                    if($schPayment->Date > $this->date) break; 
                    $this->_savingsAccounts->resetRecord();
                    $account = $this->_savingsAccounts->getRecord($row->ClientId);
                    if(is_null($account->d->Balance)) break;
                    if($account->d->Balance < $schPayment->Pmt) break;
                    /* check for problems with pmt plan */
                    if($schPayment->Pmt <= 0) {
                        $this->db->rollBack();
                        throw new Exception('LoanId: ' . $row->LoanId .'. Negative amount payments not allowed');
                    }
                    $j++;
                    $this->_insertSavingsTransaction($row,$account,$schPayment);
                    $this->_insertPayment($row,$schPayment);
                    $activeLoanUpdate = true;
                    $activeLoanData = array(
                        'BalancePrincipal' => $schPayment->BalancePrincipal,
                        'BalanceLoanInsurance' => $schPayment->BalanceLoanInsurance,
                        'BalanceHealthInsurance' => $schPayment->BalanceHealthInsurance,
                        'BalanceAdministrativeFee' => $schPayment->BalanceAdministrativeFee,
                        'PreviousPaymentDate' => $schPayment->Date
                    );
                }
                if($activeLoanUpdate) {
                    if($activeLoanData['BalancePrincipal'] > 0)
                        $this->_updateActiveLoans($row,$activeLoanData,$schPayment);
                    else
                        $this->_deleteActiveLoans($row);
                }
            } catch (Zend_Exception $e) {
                $this->db->rollBack();
                throw $e;
            }
            $this->db->commit();
        } 
    }
    
    private function _insertSavingsTransaction($row,$account,$schPayment)
    {
        $this->_savingsTransactions->insert(array(
            'Type' => 'Loan Payment',
            'ClientId' => $account->d->ClientId,
            'LoanId' => $row->LoanId,
            'Date' => $this->date,
            'Amount' => $schPayment->Pmt,
            'Balance' => $account->d->Balance - $schPayment->Pmt,
            'AccruedInterest' => SavingsAccounts::calcAccruedInterest($account),
            'UserId' =>  1,
            'Comments' => '',
            'LastEditDate' => $this->datetime,
            'LastEditUserId' => 1
        ));
    }
    
    private function _insertPayment($row,$schPayment)
    {
        $this->_payments->insert(array(
            'LoanId' => $row->LoanId,
            'Date' => $this->date,
            'Pmt' => $schPayment->Pmt,
            'Penalties' => $schPayment->Penalties,
            'Delay' => $schPayment->Delay,
            'Interest' => $schPayment->Interest,
            'LoanInsurance' => $schPayment->LoanInsurance,
            'HealthInsurance' => $schPayment->HealthInsurance,
            'AdministrativeFee' => $schPayment->AdministrativeFee,
            'Principal' => $schPayment->Principal,
            'BalancePrincipal' => $schPayment->BalancePrincipal,
            'BalanceLoanInsurance' => $schPayment->BalanceLoanInsurance,
            'BalanceHealthInsurance' => $schPayment->BalanceHealthInsurance,
            'BalanceAdministrativeFee' => $schPayment->BalanceAdministrativeFee,
            'Special' => 0,
            'UserId' => 1,
            'LastEditDate' => $this->datetime,
            'LastEditUserId' => 1
        ));
    }
    
    private function _updateActiveLoans($row,$activeLoanData,$schPayment)
    {
        $whereActiveLoans = $this->_activeLoans->getAdapter()->quoteInto('LoanId = ?', $row->LoanId);
        $this->_activeLoans->update($activeLoanData + array(
            'NextPaymentDate' => $schPayment->Date,
            'ExpectedPaymentAmount' => $schPayment->Pmt,
            'CurrentDelay' => $schPayment->Delay,
            'CurrentPenalties' => $schPayment->Penalties
        ), $whereActiveLoans);
    }
    
    private function _deleteActiveLoans($row)
    {
        /*
         * delete from active_loans
         */
        $whereActiveLoans = $this->_activeLoans->getAdapter()->quoteInto('LoanId = ?', $row->LoanId);
        $this->_activeLoans->delete($whereActiveLoans);
                    
        /*
         * log the status change
         */
        $this->_loanStatusChanges->insert(array(
            'LoanId' => $row->LoanId,
            'PreviousStatus' => 'Disbursed',
            'Status' => 'Paid',
            'Date' => $this->date,
            'Datetime' => $this->datetime,
            'UserId' => 1,
            'Comments' => ''
        ));
        
        /*
         * update status in loans
         */
        $whereLoans = $this->_loans->getAdapter()->quoteInto('LoanId = ?', $row->LoanId);
        $this->_loans->update(array(
            'Status' => 'Paid',
            'LastEditDate' => $this->datetime,
            'LastEditUserId' => 1
        ), $whereLoans);
    }
}




